package com.datagateway.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 熔断器管理器
 * 负责实现熔断器模式，包括半开、开启、关闭状态管理
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class CircuitBreakerManager {

    private static final Logger logger = LoggerFactory.getLogger(CircuitBreakerManager.class);

    @Autowired
    private AlertManager alertManager;

    /**
     * 熔断器统计
     */
    private final AtomicLong totalRequests = new AtomicLong(0);
    private final AtomicLong totalSuccessfulRequests = new AtomicLong(0);
    private final AtomicLong totalFailedRequests = new AtomicLong(0);
    private final AtomicLong totalCircuitBreakerTrips = new AtomicLong(0);

    /**
     * 熔断器配置
     */
    private boolean circuitBreakerEnabled = true;
    private int defaultFailureThreshold = 5;
    private int defaultSuccessThreshold = 3;
    private long defaultTimeoutMs = 60000;
    private long defaultRecoveryTimeoutMs = 30000;

    /**
     * 熔断器存储
     */
    private final Map<String, CircuitBreaker> circuitBreakers = new ConcurrentHashMap<>();
    private final Map<String, CircuitBreakerConfig> circuitBreakerConfigs = new ConcurrentHashMap<>();

    /**
     * 执行器
     */
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2, r -> {
        Thread t = new Thread(r, "circuit-breaker-manager");
        t.setDaemon(true);
        return t;
    });

    /**
     * 初始化熔断器管理器
     */
    public void initialize() {
        try {
            // 启动熔断器监控任务
            startCircuitBreakerMonitoringTask();
            
            logger.info("熔断器管理器初始化成功");
            
        } catch (Exception e) {
            logger.error("熔断器管理器初始化失败", e);
            alertManager.sendSystemErrorAlert("熔断器管理器初始化失败", e.getMessage());
        }
    }

    /**
     * 停止熔断器管理器
     */
    public void stop() {
        try {
            scheduler.shutdown();
            if (!scheduler.awaitTermination(30, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
            
            logger.info("熔断器管理器停止成功");
            
        } catch (Exception e) {
            logger.error("熔断器管理器停止失败", e);
        }
    }

    /**
     * 创建熔断器
     * 
     * @param key 熔断器键
     * @param failureThreshold 失败阈值
     * @param successThreshold 成功阈值
     * @param timeoutMs 超时时间
     * @param recoveryTimeoutMs 恢复超时时间
     * @return 是否创建成功
     */
    public boolean createCircuitBreaker(String key, int failureThreshold, int successThreshold, 
                                      long timeoutMs, long recoveryTimeoutMs) {
        if (!circuitBreakerEnabled) {
            logger.debug("熔断器已禁用，跳过熔断器创建: {}", key);
            return false;
        }

        try {
            CircuitBreaker circuitBreaker = new CircuitBreaker(
                key, failureThreshold, successThreshold, timeoutMs, recoveryTimeoutMs
            );

            circuitBreakers.put(key, circuitBreaker);
            
            CircuitBreakerConfig config = new CircuitBreakerConfig(
                key, failureThreshold, successThreshold, timeoutMs, recoveryTimeoutMs
            );
            circuitBreakerConfigs.put(key, config);
            
            logger.info("熔断器创建成功: {} (失败阈值: {}, 成功阈值: {}, 超时: {}ms)", 
                       key, failureThreshold, successThreshold, timeoutMs);
            
            return true;
            
        } catch (Exception e) {
            logger.error("创建熔断器失败: {}", key, e);
            alertManager.sendSystemErrorAlert("创建熔断器失败", e.getMessage());
            return false;
        }
    }

    /**
     * 执行请求（带熔断器保护）
     * 
     * @param key 熔断器键
     * @param request 请求
     * @return 执行结果
     */
    public <T> CircuitBreakerResult<T> execute(String key, CircuitBreakerRequest<T> request) {
        if (!circuitBreakerEnabled) {
            try {
                T result = request.execute();
                return new CircuitBreakerResult<>(result, true, "SUCCESS", null);
            } catch (Exception e) {
                return new CircuitBreakerResult<>(null, false, "FAILED", e.getMessage());
            }
        }

        try {
            totalRequests.incrementAndGet();
            
            CircuitBreaker circuitBreaker = circuitBreakers.get(key);
            if (circuitBreaker == null) {
                // 使用默认配置创建熔断器
                circuitBreaker = createDefaultCircuitBreaker(key);
                if (circuitBreaker == null) {
                    // 如果创建失败，直接执行请求
                    T result = request.execute();
                    return new CircuitBreakerResult<>(result, true, "SUCCESS", null);
                }
            }

            return circuitBreaker.execute(request);
            
        } catch (Exception e) {
            logger.error("执行熔断器请求失败: {}", key, e);
            totalFailedRequests.incrementAndGet();
            return new CircuitBreakerResult<>(null, false, "ERROR", e.getMessage());
        }
    }

    /**
     * 获取熔断器状态
     * 
     * @param key 熔断器键
     * @return 熔断器状态
     */
    public CircuitBreakerStatus getCircuitBreakerStatus(String key) {
        try {
            CircuitBreaker circuitBreaker = circuitBreakers.get(key);
            if (circuitBreaker == null) {
                return null;
            }

            return circuitBreaker.getStatus();
            
        } catch (Exception e) {
            logger.error("获取熔断器状态失败: {}", key, e);
            return null;
        }
    }

    /**
     * 获取所有熔断器状态
     * 
     * @return 熔断器状态列表
     */
    public List<CircuitBreakerStatus> getAllCircuitBreakerStatus() {
        try {
            List<CircuitBreakerStatus> statusList = new ArrayList<>();
            for (CircuitBreaker circuitBreaker : circuitBreakers.values()) {
                statusList.add(circuitBreaker.getStatus());
            }
            return statusList;
        } catch (Exception e) {
            logger.error("获取所有熔断器状态失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 重置熔断器
     * 
     * @param key 熔断器键
     * @return 是否重置成功
     */
    public boolean resetCircuitBreaker(String key) {
        try {
            CircuitBreaker circuitBreaker = circuitBreakers.get(key);
            if (circuitBreaker != null) {
                circuitBreaker.reset();
                logger.info("熔断器重置成功: {}", key);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            logger.error("重置熔断器失败: {}", key, e);
            return false;
        }
    }

    /**
     * 删除熔断器
     * 
     * @param key 熔断器键
     * @return 是否删除成功
     */
    public boolean removeCircuitBreaker(String key) {
        try {
            CircuitBreaker removed = circuitBreakers.remove(key);
            circuitBreakerConfigs.remove(key);
            
            if (removed != null) {
                logger.info("熔断器删除成功: {}", key);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            logger.error("删除熔断器失败: {}", key, e);
            return false;
        }
    }

    /**
     * 获取熔断器统计信息
     * 
     * @return 统计信息
     */
    public CircuitBreakerStatistics getStatistics() {
        return new CircuitBreakerStatistics(
            totalRequests.get(),
            totalSuccessfulRequests.get(),
            totalFailedRequests.get(),
            totalCircuitBreakerTrips.get(),
            circuitBreakers.size(),
            circuitBreakerConfigs.size(),
            circuitBreakerEnabled,
            defaultFailureThreshold,
            defaultSuccessThreshold,
            defaultTimeoutMs,
            System.currentTimeMillis()
        );
    }

    /**
     * 设置熔断器配置
     * 
     * @param enabled 是否启用熔断器
     * @param defaultFailureThreshold 默认失败阈值
     * @param defaultSuccessThreshold 默认成功阈值
     * @param defaultTimeoutMs 默认超时时间
     * @param defaultRecoveryTimeoutMs 默认恢复超时时间
     */
    public void setConfiguration(boolean enabled, int defaultFailureThreshold, int defaultSuccessThreshold,
                               long defaultTimeoutMs, long defaultRecoveryTimeoutMs) {
        this.circuitBreakerEnabled = enabled;
        this.defaultFailureThreshold = defaultFailureThreshold;
        this.defaultSuccessThreshold = defaultSuccessThreshold;
        this.defaultTimeoutMs = defaultTimeoutMs;
        this.defaultRecoveryTimeoutMs = defaultRecoveryTimeoutMs;
        
        logger.info("熔断器配置已更新: 启用={}, 失败阈值={}, 成功阈值={}, 超时={}ms, 恢复超时={}ms", 
                   enabled, defaultFailureThreshold, defaultSuccessThreshold, defaultTimeoutMs, defaultRecoveryTimeoutMs);
    }

    /**
     * 创建默认熔断器
     */
    private CircuitBreaker createDefaultCircuitBreaker(String key) {
        try {
            return new CircuitBreaker(key, defaultFailureThreshold, defaultSuccessThreshold, 
                defaultTimeoutMs, defaultRecoveryTimeoutMs);
        } catch (Exception e) {
            logger.error("创建默认熔断器失败: {}", key, e);
            return null;
        }
    }

    /**
     * 启动熔断器监控任务
     */
    private void startCircuitBreakerMonitoringTask() {
        scheduler.scheduleAtFixedRate(this::monitorCircuitBreakers, 
            0, 30, TimeUnit.SECONDS);
    }

    /**
     * 监控熔断器
     */
    private void monitorCircuitBreakers() {
        try {
            for (CircuitBreaker circuitBreaker : circuitBreakers.values()) {
                circuitBreaker.checkState();
            }
        } catch (Exception e) {
            logger.error("监控熔断器失败", e);
        }
    }

    /**
     * 熔断器类
     */
    public static class CircuitBreaker {
        private final String key;
        private final int failureThreshold;
        private final int successThreshold;
        private final long timeoutMs;
        private final long recoveryTimeoutMs;
        
        private CircuitBreakerState state;
        private int failureCount;
        private int successCount;
        private long lastFailureTime;
        private long lastSuccessTime;
        private final AtomicLong totalRequests;
        private final AtomicLong totalSuccessfulRequests;
        private final AtomicLong totalFailedRequests;
        private final AtomicLong totalTrips;

        public CircuitBreaker(String key, int failureThreshold, int successThreshold, 
                            long timeoutMs, long recoveryTimeoutMs) {
            this.key = key;
            this.failureThreshold = failureThreshold;
            this.successThreshold = successThreshold;
            this.timeoutMs = timeoutMs;
            this.recoveryTimeoutMs = recoveryTimeoutMs;
            this.state = CircuitBreakerState.CLOSED;
            this.failureCount = 0;
            this.successCount = 0;
            this.totalRequests = new AtomicLong(0);
            this.totalSuccessfulRequests = new AtomicLong(0);
            this.totalFailedRequests = new AtomicLong(0);
            this.totalTrips = new AtomicLong(0);
        }

        public <T> CircuitBreakerResult<T> execute(CircuitBreakerRequest<T> request) {
            totalRequests.incrementAndGet();
            
            if (state == CircuitBreakerState.OPEN) {
                if (System.currentTimeMillis() - lastFailureTime > recoveryTimeoutMs) {
                    state = CircuitBreakerState.HALF_OPEN;
                    logger.info("熔断器进入半开状态: {}", key);
                } else {
                    totalFailedRequests.incrementAndGet();
                    return new CircuitBreakerResult<>(null, false, "CIRCUIT_OPEN", "熔断器开启");
                }
            }
            
            try {
                long startTime = System.currentTimeMillis();
                T result = request.execute();
                long executionTime = System.currentTimeMillis() - startTime;
                
                if (executionTime > timeoutMs) {
                    onFailure("请求超时");
                    return new CircuitBreakerResult<>(null, false, "TIMEOUT", "请求超时");
                }
                
                onSuccess();
                return new CircuitBreakerResult<>(result, true, "SUCCESS", null);
                
            } catch (Exception e) {
                onFailure(e.getMessage());
                return new CircuitBreakerResult<>(null, false, "FAILED", e.getMessage());
            }
        }

        public CircuitBreakerStatus getStatus() {
            return new CircuitBreakerStatus(
                key,
                state,
                failureCount,
                successCount,
                totalRequests.get(),
                totalSuccessfulRequests.get(),
                totalFailedRequests.get(),
                totalTrips.get(),
                lastFailureTime,
                lastSuccessTime,
                System.currentTimeMillis()
            );
        }

        public void reset() {
            state = CircuitBreakerState.CLOSED;
            failureCount = 0;
            successCount = 0;
            logger.info("熔断器重置: {}", key);
        }

        public void checkState() {
            if (state == CircuitBreakerState.OPEN) {
                if (System.currentTimeMillis() - lastFailureTime > recoveryTimeoutMs) {
                    state = CircuitBreakerState.HALF_OPEN;
                    logger.info("熔断器进入半开状态: {}", key);
                }
            }
        }

        private void onSuccess() {
            successCount++;
            lastSuccessTime = System.currentTimeMillis();
            totalSuccessfulRequests.incrementAndGet();
            
            if (state == CircuitBreakerState.HALF_OPEN) {
                if (successCount >= successThreshold) {
                    state = CircuitBreakerState.CLOSED;
                    failureCount = 0;
                    successCount = 0;
                    logger.info("熔断器关闭: {}", key);
                }
            } else if (state == CircuitBreakerState.CLOSED) {
                failureCount = 0; // 重置失败计数
            }
        }

        private void onFailure(String error) {
            failureCount++;
            lastFailureTime = System.currentTimeMillis();
            totalFailedRequests.incrementAndGet();
            
            if (state == CircuitBreakerState.CLOSED || state == CircuitBreakerState.HALF_OPEN) {
                if (failureCount >= failureThreshold) {
                    state = CircuitBreakerState.OPEN;
                    totalTrips.incrementAndGet();
                    logger.warn("熔断器开启: {} (失败次数: {})", key, failureCount);
                }
            }
            
            if (state == CircuitBreakerState.HALF_OPEN) {
                successCount = 0; // 重置成功计数
            }
        }
    }

    /**
     * 熔断器状态枚举
     */
    public enum CircuitBreakerState {
        CLOSED,    // 关闭状态
        OPEN,      // 开启状态
        HALF_OPEN  // 半开状态
    }

    /**
     * 熔断器请求接口
     */
    @FunctionalInterface
    public interface CircuitBreakerRequest<T> {
        T execute() throws Exception;
    }

    /**
     * 熔断器结果类
     */
    public static class CircuitBreakerResult<T> {
        private final T result;
        private final boolean success;
        private final String status;
        private final String errorMessage;

        public CircuitBreakerResult(T result, boolean success, String status, String errorMessage) {
            this.result = result;
            this.success = success;
            this.status = status;
            this.errorMessage = errorMessage;
        }

        // Getter方法
        public T getResult() { return result; }
        public boolean isSuccess() { return success; }
        public String getStatus() { return status; }
        public String getErrorMessage() { return errorMessage; }
    }

    /**
     * 熔断器状态类
     */
    public static class CircuitBreakerStatus {
        private final String key;
        private final CircuitBreakerState state;
        private final int failureCount;
        private final int successCount;
        private final long totalRequests;
        private final long totalSuccessfulRequests;
        private final long totalFailedRequests;
        private final long totalTrips;
        private final long lastFailureTime;
        private final long lastSuccessTime;
        private final long timestamp;

        public CircuitBreakerStatus(String key, CircuitBreakerState state, int failureCount, int successCount,
                                  long totalRequests, long totalSuccessfulRequests, long totalFailedRequests,
                                  long totalTrips, long lastFailureTime, long lastSuccessTime, long timestamp) {
            this.key = key;
            this.state = state;
            this.failureCount = failureCount;
            this.successCount = successCount;
            this.totalRequests = totalRequests;
            this.totalSuccessfulRequests = totalSuccessfulRequests;
            this.totalFailedRequests = totalFailedRequests;
            this.totalTrips = totalTrips;
            this.lastFailureTime = lastFailureTime;
            this.lastSuccessTime = lastSuccessTime;
            this.timestamp = timestamp;
        }

        // Getter方法
        public String getKey() { return key; }
        public CircuitBreakerState getState() { return state; }
        public int getFailureCount() { return failureCount; }
        public int getSuccessCount() { return successCount; }
        public long getTotalRequests() { return totalRequests; }
        public long getTotalSuccessfulRequests() { return totalSuccessfulRequests; }
        public long getTotalFailedRequests() { return totalFailedRequests; }
        public long getTotalTrips() { return totalTrips; }
        public long getLastFailureTime() { return lastFailureTime; }
        public long getLastSuccessTime() { return lastSuccessTime; }
        public long getTimestamp() { return timestamp; }
        
        public double getSuccessRate() {
            return totalRequests > 0 ? (double) totalSuccessfulRequests / totalRequests : 0.0;
        }
        
        public double getFailureRate() {
            return totalRequests > 0 ? (double) totalFailedRequests / totalRequests : 0.0;
        }
    }

    /**
     * 熔断器配置类
     */
    public static class CircuitBreakerConfig {
        private final String key;
        private final int failureThreshold;
        private final int successThreshold;
        private final long timeoutMs;
        private final long recoveryTimeoutMs;

        public CircuitBreakerConfig(String key, int failureThreshold, int successThreshold,
                                  long timeoutMs, long recoveryTimeoutMs) {
            this.key = key;
            this.failureThreshold = failureThreshold;
            this.successThreshold = successThreshold;
            this.timeoutMs = timeoutMs;
            this.recoveryTimeoutMs = recoveryTimeoutMs;
        }

        // Getter方法
        public String getKey() { return key; }
        public int getFailureThreshold() { return failureThreshold; }
        public int getSuccessThreshold() { return successThreshold; }
        public long getTimeoutMs() { return timeoutMs; }
        public long getRecoveryTimeoutMs() { return recoveryTimeoutMs; }
    }

    /**
     * 熔断器统计信息类
     */
    public static class CircuitBreakerStatistics {
        private final long totalRequests;
        private final long totalSuccessfulRequests;
        private final long totalFailedRequests;
        private final long totalCircuitBreakerTrips;
        private final int activeCircuitBreakers;
        private final int totalConfigs;
        private final boolean circuitBreakerEnabled;
        private final int defaultFailureThreshold;
        private final int defaultSuccessThreshold;
        private final long defaultTimeoutMs;
        private final long timestamp;

        public CircuitBreakerStatistics(long totalRequests, long totalSuccessfulRequests, long totalFailedRequests,
                                      long totalCircuitBreakerTrips, int activeCircuitBreakers, int totalConfigs,
                                      boolean circuitBreakerEnabled, int defaultFailureThreshold, int defaultSuccessThreshold,
                                      long defaultTimeoutMs, long timestamp) {
            this.totalRequests = totalRequests;
            this.totalSuccessfulRequests = totalSuccessfulRequests;
            this.totalFailedRequests = totalFailedRequests;
            this.totalCircuitBreakerTrips = totalCircuitBreakerTrips;
            this.activeCircuitBreakers = activeCircuitBreakers;
            this.totalConfigs = totalConfigs;
            this.circuitBreakerEnabled = circuitBreakerEnabled;
            this.defaultFailureThreshold = defaultFailureThreshold;
            this.defaultSuccessThreshold = defaultSuccessThreshold;
            this.defaultTimeoutMs = defaultTimeoutMs;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getTotalRequests() { return totalRequests; }
        public long getTotalSuccessfulRequests() { return totalSuccessfulRequests; }
        public long getTotalFailedRequests() { return totalFailedRequests; }
        public long getTotalCircuitBreakerTrips() { return totalCircuitBreakerTrips; }
        public int getActiveCircuitBreakers() { return activeCircuitBreakers; }
        public int getTotalConfigs() { return totalConfigs; }
        public boolean isCircuitBreakerEnabled() { return circuitBreakerEnabled; }
        public int getDefaultFailureThreshold() { return defaultFailureThreshold; }
        public int getDefaultSuccessThreshold() { return defaultSuccessThreshold; }
        public long getDefaultTimeoutMs() { return defaultTimeoutMs; }
        public long getTimestamp() { return timestamp; }
        
        public double getSuccessRate() {
            return totalRequests > 0 ? (double) totalSuccessfulRequests / totalRequests : 0.0;
        }
        
        public double getFailureRate() {
            return totalRequests > 0 ? (double) totalFailedRequests / totalRequests : 0.0;
        }
    }
}
